/*
 * © Copyright 2011 Romain Marteau, Matthieu Totet
 * 
 *    This file is part of VineaToum.
 *
 *    VineaToum is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    VineaToum is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with VineaToum.  If not, see <http://www.gnu.org/licenses/>.
 *    
 */

package org.vineatoum.business.state.abstraction;

import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.xml.bind.annotation.XmlTransient;

import org.vineatoum.business.Cuve;
import org.vineatoum.business.abstraction.BusinessAbstract;
import org.vineatoum.business.action.abstraction.Action;
import org.vineatoum.business.action.abstraction.Analyse;
import org.vineatoum.business.tracking.ITrackableElement;
import org.vineatoum.business.tracking.TrackInfo;

public abstract class VinAbstract extends BusinessAbstract implements ITrackableElement {
	protected long id;
	protected String name;
	protected float quantity;
	protected Cuve cuve;
	@XmlTransient
	protected Date creationDate = new Date();

	public Date getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Date creationDate) {
		this.creationDate = creationDate;
	}

	/**
	 * Tracking
	 */
	protected Set<VinAbstract> origines = new HashSet<VinAbstract>();
	protected Set<VinAbstract> fils = new HashSet<VinAbstract>();

	public void addNewFils(VinAbstract va) {
		fils.add(va);
	}

	public void addNewOrigines(VinAbstract va) {
		origines.add(va);
	}

	/**
	 * Opérations subies
	 */
	protected Set<Action> actions = new HashSet<Action>();
	protected Set<Analyse> analyses = new HashSet<Analyse>();

	/**
	 * Etat du vin
	 */
	protected boolean actifFlag;

	// private Cuve actualC	ontenant;

	// private Stack<Action> historyAction = new Stack<Action>();

	// public VinAbstract (Cuve putIn) {
	// setActualContenant(putIn);
	// }

	public VinAbstract() {
	}

	// public Cuve getActualContenant() {
	// return actualContenant;
	// }

	// public void setActualContenant(Cuve putIn) {
	// this.actualContenant = putIn;
	// this.actualContenant.setActualVin(this);
	// }
	// public void addAction(Action a) {
	// historyAction.add(a);
	// }
	protected void getOriginesTrackingInfo(TrackInfo tracked, VinAbstract va) {
		TrackInfo temp = new TrackInfo();
		temp.setTrackedElement(va);
		tracked.addFromElements(temp);
		if (!va.origines.isEmpty()) {
			for (Iterator<VinAbstract> iterator = va.origines.iterator(); iterator.hasNext();) {
				VinAbstract origine = (VinAbstract) iterator.next();
				getOriginesTrackingInfo(tracked, origine);
			}
		}
	}

	protected void getFilsTrackingInfo(TrackInfo tracked, VinAbstract va) {
		TrackInfo temp = new TrackInfo();
		temp.setTrackedElement(va);
		tracked.addChildElements(temp);
		if (!va.fils.isEmpty()) {
			for (Iterator<VinAbstract> iterator = va.fils.iterator(); iterator.hasNext();) {
				VinAbstract origine = (VinAbstract) iterator.next();
				getFilsTrackingInfo(tracked, origine);
			}
		}
	}

	public TrackInfo getTrackingInfo() {
		TrackInfo temp = new TrackInfo();
		temp.setTrackedElement(this);
		getOriginesTrackingInfo(temp, this);
		getFilsTrackingInfo(temp, this);
//		temp.getListedTracking().add(this);
		/*
		 * if (!fils.isEmpty()) for (Iterator<VinAbstract> iterator =
		 * fils.iterator(); iterator .hasNext();) {
		 * 
		 * VinAbstract fils = (VinAbstract) iterator.next();
		 * getFilsTrackingInfo(temp, fils);
		 * 
		 * }
		 */

		return temp;
	}


	public void getTracking() {
		System.out.println(this);
		for (Iterator<VinAbstract> iterator = origines.iterator(); iterator.hasNext();) {
			VinAbstract origine = (VinAbstract) iterator.next();
			origine.getTracking();
		}
		// System.out.println(this);
		// marc.getTracking();
		// super.getTracking();
	}

	@Override
	public int compareTo(ITrackableElement element) {
		try { //TODO Maybe create a specific function to sort. Instead of CompareTo. What if we want to compare with another attribute ? 
			VinAbstract other = (VinAbstract) element;
			return this.creationDate.compareTo(other.getCreationDate());
		} catch (ClassCastException e) {
			//TODO Generate error
			return -1;
		}
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	public void setQuantity(float qte) {
		this.quantity = qte;
	}
	public float getQuantity() {
		return quantity;
	}
	
	public void setCuve(Cuve cuve) {
		this.cuve = cuve;
	}
	public Cuve getCuve() {
		return cuve;
	}

	public void addAction(Action action) {
		actions.add(action);
	}
	
	public void addAnalyse(Analyse analyse) {
		analyses.add(analyse);
	}
	
	public Set<Action> getActions() {
		return actions;
	}
	
	public Set<Analyse> getAnalyses() {
		return analyses;
	}
	
	
}
